<template>
  <a-upload
    v-bind="omit(props, ['onUpdate:fileList'])"
    :disabled="loading"
    listType="picture-card"
    v-model:fileList="fileList"
    :action="uploadUrl"
    :headers="{ [TOKEN_HEADER]: `Bearer ${LocalStorage.get('token')}` }"
    @change="(info: any) => handleUploadChange(info)"
    :beforeUpload="beforeUpload"
  >
    <a-spin :spinning="loading">
      <component v-if="$slots.default" :is="$slots.default" />
      <div v-else>
        <PlusOutlined />
        <div>文件上传</div>
      </div>
    </a-spin>
  </a-upload>
</template>
<script lang="ts" setup>
  import { TOKEN_HEADER } from '@/api/http';
  import { LocalStorage } from '@/utils/utils';
  import type { UploadFile, UploadProps } from 'ant-design-vue';
  import { PlusOutlined } from '@ant-design/icons-vue';
  import { filter, isString, omit } from 'lodash-es';
  import { bizApi } from '@/api/biz';
  import { computed, ref } from 'vue';
  interface FileUploadProps extends Omit<UploadProps, 'fileList'> {
    fileList: UploadFile[] | string[];
  }

  const props = withDefaults(defineProps<FileUploadProps>(), {
    fileList: () => [],
    openFileDialogOnClick: true,
  });

  const emits = defineEmits<{
    change: [file: UploadFile];
    'update:fileList': [fileList: UploadFile[]];
  }>();
  // 文件上传地址
  const uploadUrl = `${process.env.VITE_APP_API_URL}/upload`;
  // 数据回显时处于 loading 状态禁止编辑
  const loading = ref(false);

  // 上传后将url添加到file中，实现预览下载功能
  function handleUploadChange(info: ParametersOne<UploadProps['onChange']>) {
    if (info.file.status === 'done') {
      info.file.url = (info.file.response as any).biz_content.fileUrl;
    }
    emits('update:fileList', info.fileList);
  }
  // 上传文件列表（数据回显场景下获取的是 fileKey，需要向后端发送请求换为实际的 url）
  const fileList = computed(() => {
    const fileList = filter(props.fileList, (item) => !isString(item)) as UploadFile[];
    const fileKey: string[] = filter(props.fileList, isString);

    // 如果有需要回显的数据，发送请求获取
    if (fileKey.length) {
      getFileListByFileKey(fileKey, fileList);
    }
    return fileList;
  });

  /** 将文件key转换成文件url */
  async function getFileListByFileKey(fileKey: string[], fileList: UploadFile[]) {
    if (loading.value) {
      return;
    }
    loading.value = true;
    const result = await bizApi.httpList('base.manage.file.ServiceImpl.getUrl', {
      fileKey,
    });
    const wrapFileList = wrapUploadFileList(result.fileUrl, fileKey);
    loading.value = false;
    // 请求成功后更新 fileList 回显数据
    emits('update:fileList', [...fileList, ...wrapFileList]);
  }
  /**
   * Upload 组件的数据回显
   * */
  const wrapUploadFileList = (urls: string[], fileKey: string[]): UploadFile[] => {
    return urls.map((url, index) => ({
      uid: url,
      name: '文件',
      thumbUrl: url,
      size: 0,
      status: 'done',
      response: {
        biz_content: {
          fileKey: fileKey[index],
          sub_code: 100000,
        },
      },
    }));
  };
</script>
